package one.stand.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.wxpay.sdk.WXPayUtil;
import com.qq.weixin.mp.aes.WXBizMsgCrypt;
import one.stand.code.RedisCode;
import one.stand.entity.UserInfoEntity;
import one.stand.enums.CompanyVersionEnums;
import one.stand.enums.LoginEnum;
import one.stand.mapper.CompanyAccountMapper;
import one.stand.mapper.EssayVisitorsDataMapper;
import one.stand.model.*;
import one.stand.model.essay.EssayShareRecordModel;
import one.stand.model.essay.EssayVisitorsDataModel;
import one.stand.model.live.WxShareDynamicModel;
import one.stand.request.CompanyAccountRequest;
import one.stand.request.ComponentProgramRequest;
import one.stand.request.ComponentVerifyTicketRequest;
import one.stand.request.wx.AuthSnsapiUserinfoRequest;
import one.stand.request.wx.ShareDynamicRequest;
import one.stand.request.wx.WxMsgRequest;
import one.stand.response.wx.AuthSnsapiUserinfoResponse;
import one.stand.service.CodeService;
import one.stand.service.CompanyAccontService;
import one.stand.service.WxService;
import one.stand.util.DateUtil;
import one.stand.util.HttpUtil;
import one.stand.util.RedisUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.nio.charset.StandardCharsets;
import java.util.Map;

/**
 * @author: QIK
 * @CreateDate: 2019/5/9 14:42
 */
@Service
@Transactional
public class WxServiceImpl extends PublicBaseService implements WxService {


    @Autowired
    CompanyAccountMapper companyAccountMapper;

    @Autowired
    EssayVisitorsDataMapper essayVisitorsDataMapper;

    @Autowired
    private CompanyAccontService companyAccontService;

    @Autowired
    private WxMessageServiceImpl wxMessageService;

    @Value("${templateHtml}")
    private String templateHtml;

    @Autowired
    RedisUtil redisUtil;

    @Value("${appId}")
    private String appId;

    @Override
    public String wxcallback(ComponentVerifyTicketRequest request) {
        log.info("wxcallback:{}",request);
        String nonce = request.getNonce();
        String timestamp = request.getTimestamp();
        String msg_signature = request.getMsg_signature();
        String xml = request.getXml();
        try {
            if (StringUtils.isBlank(msg_signature)) {
                log.info("没有获取到微信发送过来的消息----------");
                return wxPayService.fail();
            }
            Map<String,String> map = WXPayUtil.xmlToMap(xml);
            WXBizMsgCrypt componentAccount = new WXBizMsgCrypt(componentConfig.getToken(), componentConfig.getMessagekey(), componentConfig.getAppid());
            xml = componentAccount.decryptMsg(msg_signature, timestamp, nonce, map.get("Encrypt"));
            map=WXPayUtil.xmlToMap(xml);
            log.info("解密后的xml:{}",xml);
            if(map.get("InfoType").equals("component_verify_ticket")){
                String componentVerifyTicket=map.get("ComponentVerifyTicket");
                if(!StringUtils.isBlank(componentVerifyTicket)){
                    redisUtil.set(RedisCode.getTicket(request.getAppid()),componentVerifyTicket);
                }
            }

        } catch (Exception e) {
            log.error("回调参数ticket[异常]", e);
        }
        return SUCCESS.toLowerCase();
    }
    @Autowired
    CodeService codeService;

    @Override
    public String wxcallback(ComponentProgramRequest request) {
        log.info("微信回调通知请求，请求参数：{}", JSON.toJSONString(request));
        String nonce =request.getNonce();
        String timestamp = request.getTimestamp();
        String msg_signature = request.getMsg_signature();
        String xml=request.getXml();
        try {
            if (StringUtils.isBlank(msg_signature)) {
                log.info("没有获取到微信发送过来的消息----------");
                return wxPayService.fail();
            }
            log.info("获取解密前的postdata的xml:{}", xml);
            Map<String,String> map=WXPayUtil.xmlToMap(xml);
            WXBizMsgCrypt componentAccount = new WXBizMsgCrypt(componentConfig.getToken(), componentConfig.getMessagekey(), componentConfig.getAppid());
            xml = componentAccount.decryptMsg(msg_signature, timestamp, nonce, map.get("Encrypt"));
            map=WXPayUtil.xmlToMap(xml);
            log.info("解密后的xml:{}",xml);
            if(map.get("MsgType").equals("event")){
                CompanyVersionModel companyVersionModel=companyVersionMapper.selectAccountByAppId(new CompanyVersionModel(){{
                    setAppId(request.getAppid());
                }});
                log.info("收到审核结果通知：{}------{}",request.getAppid(),xml);
                String Event=map.get("Event");
                if("weapp_audit_success".equals(Event)){
                    log.info("小程序审核通过：{}",request.getAppid());
                    if(null!=companyVersionModel){
                        //自动发布功能  codeService.release(companyVersionModel.getVersionId(),request.getAppid());
                        companyVersionModel.setState(CompanyVersionEnums.audit_success.getCode());
                        companyVersionMapper.updateByPrimaryKeySelective(companyVersionModel);
                    }else {
                        log.info("版本信息错误");
                    }
                }else{
                    log.info("小程序审核不通过");
                    log.info("小程序审核失败原因：{}------{}",request.getAppid(),map.get("Reason"));
                    if(companyVersionModel==null){
                        log.info("版本信息错误");
                    }else {
                        companyVersionModel.setState(CompanyVersionEnums.audit_err.getCode());
                        companyVersionModel.setRemark(map.get("Reason"));
                        companyVersionMapper.updateByPrimaryKeySelective(companyVersionModel);
                        log.info("版本信息错误");
                    }
                }
            }else if(map.get("Content").toString().equals("1")){
                //inMessage.getFromUser(),request.getAppid(),inMessage.getContent()
                this.sendSmMsg(map.get("FromUserName"),request.getAppid(),map.get("Content").toString());
            }

        } catch (Exception e) {
            log.error("微信回调流program[异常]", e);
        }
        return SUCCESS.toLowerCase();
    }

    /**
     * 发送小程序消息
     * @param openId
     * @param appIdSm
     * @param content
     */
    @Override
    @Async
    public void sendSmMsg(String openId,String appIdSm,String content){

        CompanyAccountModel companyAccountModel = this.companyAccontService.selectByCompanyKey(new CompanyAccountRequest() {{
            setAppId(appIdSm);
        }});
        log.info("companyAccountModel:{}",companyAccountModel);

        //获取公司token
        final String token = this.wxMessageService.getWxToken(appIdSm,companyAccountModel.getAppSecret());

        JSONObject msg = new JSONObject();
        msg.put("touser",openId);
        msg.put("msgtype",content.equals("1") ? "link" : "text");
        JSONObject link = new JSONObject();

        WxShareDynamicModel wxShareDynamicModel = this.queryUserShareDynamic(openId);
        if(wxShareDynamicModel != null){
            link.put("title",wxShareDynamicModel.getTitle());
            link.put("description",wxShareDynamicModel.getOriginAuthor());
            //
            String url = templateHtml + String.format("?dynamicId=%s&userId=%s&appid=%s",wxShareDynamicModel.getDynamicId(),wxShareDynamicModel.getUserId(),appId);
            link.put("url",wxShareDynamicModel.getUrl() == null ? url : wxShareDynamicModel.getUrl());

            //拆分图片。保存时拼接
            if(wxShareDynamicModel.getPhotos().contains(",")){
                link.put("thumb_url",wxShareDynamicModel.getPhotos().split(",")[0]);
            }else{
                link.put("thumb_url",wxShareDynamicModel.getPhotos());
            }
        }
        if(content.equals("1")){
            msg.put("link",link);
        }else{
            JSONObject text = new JSONObject();
            text.put("content","欢迎咨询壹脉名片!");
            msg.put("text",text);
        }

        log.info("requestUrlParam:{}",msg);
        String url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" + token;
        String result = HttpUtil.sendPostJson(url,msg);
        log.info("sendmsg:{}",result);
    }

    @Transactional
    @Override
    public AuthSnsapiUserinfoResponse wxAuth(AuthSnsapiUserinfoRequest body) {
        AuthSnsapiUserinfoResponse response = new AuthSnsapiUserinfoResponse();
        //获客数 同一用户多次浏览算一次。浏览次数。统一用户浏览多次算多次
        //添加获客文章分享数据，详情和列表是从分享表查询
        log.info("wechatCallback:{}",body);
        //appId 为公众号id
        //查询公司秘钥 state=格式 appid+'_'+dynamicId
        final String appid = body.getState().split("=")[0];
        final String dynamicId = body.getState().split("=")[1];

        //按appId查询公司配置的账户秘钥
        CompanyAccountModel companyAccountModel = companyAccountMapper.select(new CompanyAccountModel() {{setAppId(appid);}});
        if(companyAccountModel != null){
            String url = String.format("https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code",appid,companyAccountModel.getAppSecret(),body.getCode());
            log.info("url:{}",url);
            String result = HttpUtil.sendGet(url);
            JSONObject token = JSONObject.parseObject(result);
            log.info("token:{}",token);
            if(!token.containsKey("openid")){
                return response;
            }

            EssayVisitorsDataModel visitorsDataModel = this.essayVisitorsDataMapper.queryByOpenId(token.getString("openid"),Integer.valueOf(dynamicId));
            //查询用户最新分享的文章
            EssayShareRecordModel recordModel = this.essayShareRecordMapper.queryByDyanmicId(dynamicId);
            //已经分享则不需要拉起授权
            if(visitorsDataModel != null){
                log.info("recordModel_:{},{}",recordModel,dynamicId);
                //更新访问数据
                visitorsDataModel.setSumNum(visitorsDataModel.getSumNum() + 1 );
                essayVisitorsDataMapper.update(visitorsDataModel);

                return getModel(recordModel,response,token.getString("openid"),appid,visitorsDataModel);
            }
            //获取用户信息
            String userInfoUrl = String.format("https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN",token.getString("access_token"),token.getString("openid"));
            log.info("getUser:{}",userInfoUrl);
            String userInfo = HttpUtil.sendGet(userInfoUrl);
            log.info("userInfo:{}",userInfo);
            //添加访客数据
            visitorsDataModel = checkOpenUser(userInfo,dynamicId);
            log.info("recordModel_:{},{}",recordModel,dynamicId);

            return getModel(recordModel,response,token.getString("openid"),appid,visitorsDataModel);
        }else{
            log.info("wechatCallback:公众号appid配置错误");
        }
        return response;
    }

    @Override
    public WxShareDynamicModel queryUserShareDynamic(String openId) {
        return this.dynamicMapper.selectQueryUserShareLast(openId);
    }

    @Override
    public String getTicketToken(WxMsgRequest request) {

        CompanyAccountModel companyAccountModel = companyAccountMapper.select(new CompanyAccountModel() {{setAppId(request.getAppid());}});
        if(companyAccountModel != null){

            String url = String.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s",request.getAppid(),companyAccountModel.getAppSecret());
            log.info("url:{}",url);
            String result = HttpUtil.sendGet(url);
            JSONObject token = JSONObject.parseObject(result);
            log.info("ticketToken:{}",token);
            if(!token.containsKey("access_token")){
                log.info("获取token错误:{}",request);
                return null;
            }

            //获取ticket信息
            String ticketUrl = String.format(" https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=%s&type=jsapi",token.getString("access_token"));
            log.info("ticketUrl:{}",ticketUrl);
            String ticketInfo = HttpUtil.sendGet(ticketUrl);
            log.info("ticketUrl:{}",ticketInfo);
            JSONObject jsonObject = JSONObject.parseObject(ticketInfo);
            if(jsonObject.containsKey("errcode") && jsonObject.getString("errcode").equals("0")){
                return jsonObject.getString("ticket");
            }
            return null;
        }else{
            log.info("获取ticket失败");
        }
        return null;
    }

    /**
     * 更新分享次数
     * 0 成功 1失败
     * @param request
     * @return
     */
    @Override
    public String updateShareNum(ShareDynamicRequest request) {
        EssayShareRecordModel recordModel = this.essayShareRecordMapper.queryByDyanmicId(String.valueOf(request.getDynamicId()));
        if(recordModel != null){
            recordModel.setShareNum(recordModel.getShareNum() + 1);
            this.essayShareRecordMapper.update(recordModel);
            return "0";
        }
        return "1";
    }

    /**
     * 更新浏览次数。同一用户浏览几次算几次
     * @param dynamicId
     * @return
     */
    @Override
    public String updateSeeNum(Integer dynamicId){
        EssayShareRecordModel recordModel = this.essayShareRecordMapper.queryByDyanmicId(String.valueOf(dynamicId));
        if(recordModel != null){
            recordModel.setSeeNum(recordModel.getSeeNum() + 1);
            this.essayShareRecordMapper.update(recordModel);
            return "0";
        }
        return "1";
    }

    /**
     * 0 成功 1失败
     * @param request
     * @return
     */
    @Override
    public String updateSeeTime(ShareDynamicRequest request) {
        EssayShareRecordModel recordModel = this.essayShareRecordMapper.queryByDyanmicId(String.valueOf(request.getDynamicId()));
        if(recordModel != null){
            recordModel.setShareNum(recordModel.getShareNum() + 1);
            this.essayShareRecordMapper.update(recordModel);
            return "0";
        }
        return "1";
    }

    /**
     * 获取重定向数据
     * @param shareRecordModel
     * @param response
     * @param appid appid
     * @return
     */
    AuthSnsapiUserinfoResponse getModel(EssayShareRecordModel shareRecordModel,AuthSnsapiUserinfoResponse response,String openId,String appid,EssayVisitorsDataModel visitorsDataModel){
        if(shareRecordModel != null){
            if(response == null){
                response = new AuthSnsapiUserinfoResponse();
            }
            //更新访问次数
            shareRecordModel.setSeeNum(shareRecordModel.getSeeNum() == null ? 1 : shareRecordModel.getSeeNum() + 1);
            shareRecordModel.setWinCustomers(shareRecordModel.getWinCustomers() + 1);
            this.essayShareRecordMapper.update(shareRecordModel);

            String url = templateHtml + String.format("?dynamicId=%s&userId=%s&openId=%s",shareRecordModel.getDynamicId(),shareRecordModel.getUserId(),openId);
            log.info("templateHtml:{},response:{},{}",url,response,shareRecordModel);
            response.setDynamicId(shareRecordModel.getDynamicId());
            response.setOpenId(openId);
            response.setUrl(  url.concat("&appid=").concat(appid));
            response.setUserId(shareRecordModel.getUserId());
            //第二次访问直接返回数据  //检查用户是否已经访问过如果是则直接返回
            log.info("response:{}",response);
            syncSeeRecord(shareRecordModel,visitorsDataModel);
            return response;
        }
        return null;
    }

    /**
     * 同步用户查看记录到系统表
     * @param shareRecordModel
     */
    private void syncSeeRecord(EssayShareRecordModel shareRecordModel,EssayVisitorsDataModel visitorsDataModel){

        BusinessCardModel businessCardModel = this.businessCardMapper.select(new BusinessCardModel(){{setUserId(shareRecordModel.getUserId().intValue());}});
        if(businessCardModel != null){
            //创建访问用户信息到系统用户表
            //通过union_id 查询用户是否存在如果不存在则创建新用户
            UserModel userModel = this.userMapper.select(new UserModel(){{visitorsDataModel.getUnionId();}});
            if(userModel != null){
                log.info("名片信息:{},userModel:{}",businessCardModel,userModel);
                //添加访问数据 已经存在的用户添加访问数据
                this.addSeeRecord(userModel.getUserId().intValue(),businessCardModel.getCardId(),shareRecordModel.getCompanyId().intValue(),4,shareRecordModel.getDynamicId().intValue(),0);
            }else{
                userModel =  this.initUser(visitorsDataModel,shareRecordModel);
                log.info("名片信息:{},userModel:{}",businessCardModel,userModel);
                if(userModel != null){
                    this.addSeeRecord(userModel.getUserId().intValue(),businessCardModel.getCardId(),shareRecordModel.getCompanyId().intValue(),4,shareRecordModel.getDynamicId().intValue(),0);
                }
            }
        }else{
            log.info("获取用户名片异常:{}",shareRecordModel);
        }
    }

    /**
     * h5授权创建用户信息
     */
    private UserModel initUser(EssayVisitorsDataModel visitorsDataModel,EssayShareRecordModel shareRecordModel){
        log.info("initUser:{}",visitorsDataModel);
        UserModel inModel = new UserModel();

        //todo 待处理用户登录时检查是否存在名片，如果是则返回名片的头像名称
        inModel.setAvatarUrl(visitorsDataModel.getHeadImgurl());
        inModel.setGender(Integer.valueOf(visitorsDataModel.getSex()));
        inModel.setCity(visitorsDataModel.getCity());
        inModel.setProvince(visitorsDataModel.getProvince());
        //inModel.setCountry(visitorsDataModel.getc("country"));
        inModel.setNickeName(encodingNickName(visitorsDataModel.getNickname()));
        inModel.setCreateTime(currentDate());
        inModel.setUnionid(visitorsDataModel.getUnionId());
        inModel.setEnterpriseId(shareRecordModel.getCompanyId().intValue());
        //h5创建的用户 openid和crmopenid为空

        userMapper.insertSelective(inModel);
        return inModel;
    }

    /**
     * 编码用户昵称
     */
    private String encodingNickName(String nickName) {
        return new String(java.util.Base64.getEncoder().encode(nickName.getBytes()), StandardCharsets.UTF_8);
    }

    /**
     * 用户访问业务处理
     * //        auth
     * // {"openid":"oOpa_0R2qgrODzt1b20w0UwzyHqU","nickname":"Never","sex":1,"language":"zh_CN","city":"","province":"福莫萨",
     * // "country":"阿根廷","headimgurl":"http:\/\/thirdwx.qlogo.cn\/mmopen\/vi_32\/DYAIOgq83eq5TA4wlZqSGUaNxWjdVbKdU0Bsjl9m4QnLpICpzKQfSxv5aCu1vsYVRAr7Qc5XIQ9jNagcibAxfOA\/132",
     * // "privilege":[],"unionid":"o1jEn1i1odfCNgLQ-Gve3L5TSGeo"}
     * @param
     */
    EssayVisitorsDataModel checkOpenUser(String userInfo,String dynamicId){
        DynamicModel dynamicModel = this.dynamicMapper.selectByPrimaryKey(Integer.valueOf(dynamicId));
        if(dynamicModel != null){
            UserInfoEntity userInfoEntity = JSONObject.parseObject(userInfo,UserInfoEntity.class);
            log.info("userInfoEntity:{},{}",userInfoEntity,dynamicModel);
            EssayVisitorsDataModel model = new EssayVisitorsDataModel();
            BeanUtils.copyProperties(userInfoEntity,model);
            model.setDynamicId(Long.valueOf(dynamicId));

            BusinessCardModel cardModel = this.businessCardMapper.queryUserById(dynamicModel.getCreateUserId());
            if(cardModel != null){
                //业务员
                model.setCardId(Long.valueOf(cardModel.getCardId()));
            }
            log.info("dynamicModel:{}",dynamicModel);
            model.setSource(3);
            model.setVisitTime(DateUtil.now());
            model.setSumNum(1);
            model.setSumTimes(0);
            model.setForwardfNum(0);
            model.setCreatedTime(DateUtil.now());
            if(dynamicModel.getCompanyId() != null){
                model.setCompanyId(Long.valueOf(dynamicModel.getCompanyId()));
            }
            log.info("model:{}",model);
            //添加访客数据
            this.essayVisitorsDataMapper.insert(model);

            return model;
        }
        log.info("动态数据错误!!");
        return null;
    }


}
